package cn.larry.tools.rsa;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

public class RSATool {
    /*
     * @Title: sign
     * @Description:私钥签名
     * @param data       待签名字符串
     * @param privateKey 私钥
     * @throws Exception
     * @return: String
     */
    public static String sign(String data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        Security.addProvider(new BouncyCastleProvider());
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance("SHA256WithRSA");
        signature.initSign(privateK);
        signature.update(data.getBytes());
        byte[] result = signature.sign();
        return Base64.encodeBase64String(result);
    }

    /**
     * @param data      已签名数据
     * @param publicKey 公钥
     * @param sign      签名
     * @throws Exception
     * @Title: verify
     * @Description: 公钥验签
     * @return: boolean
     */
    public static boolean verify(String data, String publicKey, String sign) throws Exception {
        Signature signature = Signature.getInstance("SHA256WithRSA");
        PublicKey key = KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(publicKey)));
        signature.initVerify(key);
        signature.update(data.getBytes());
        return signature.verify(Base64.decodeBase64(sign));
    }

    /**
     * 排序拼接需要验签的数据
     * @param data
     * @return
     */
    public static String getReqStr(Map<String, Object> data){
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals("sign")||k.equals("resultCode")||k.equals("resultMsg")) {
                continue;
            }
            // 参数值为空，则不参与签名
            if (data.get(k) != null && data.get(k).toString().trim().length() > 0) {
                sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");
            }
        }
        return sb.toString().substring(0,sb.toString().lastIndexOf("&"));
    }
    
    /**
     * 排序拼接需要加签的数据
     * @param data
     * @return
     */
    public static String getRespStr(Map<String, Object> data){
    	Set<String> keySet = data.keySet();
    	String[] keyArray = keySet.toArray(new String[keySet.size()]);
    	Arrays.sort(keyArray);
    	StringBuilder sb = new StringBuilder();
    	for (String k : keyArray) {
    		if (k.equals("sign")) 
    			continue;

    		// 参数值为空，则不参与签名
    		if (data.get(k) != null && data.get(k).toString().trim().length() > 0) {
    			sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");
    		}
    	}
    	return sb.toString().substring(0,sb.toString().lastIndexOf("&"));
    }
}
